package org.example.demo.service;

import java.lang.Exception;
import java.lang.String;
import java.util.Arrays;
import javax.annotation.PostConstruct;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.example.demo.model.bo.GoodsAddGoodsInputBO;
import org.example.demo.model.bo.GoodsGetGoodsInputBO;
import org.example.demo.model.bo.GoodsRemoveGoodsInputBO;
import org.example.demo.model.bo.GoodsTransferGoodsInputBO;
import org.example.demo.model.bo.GoodsUpdateGoodsInputBO;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.transaction.manager.AssembleTransactionProcessor;
import org.fisco.bcos.sdk.transaction.manager.TransactionProcessorFactory;
import org.fisco.bcos.sdk.transaction.model.dto.CallResponse;
import org.fisco.bcos.sdk.transaction.model.dto.TransactionResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.example.demo.model.GoodsInfo;
import org.example.demo.raw.Goods;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple6;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.transaction.model.exception.ContractException;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple7;
import org.example.demo.service.TransferTimeService;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.lang.reflect.Method;
import java.util.stream.Collectors;
import java.util.Collections;
import java.util.ArrayList;

@Service
@NoArgsConstructor
@Data
public class GoodsService {
  public static final String ABI = org.example.demo.utils.IOUtil.readResourceAsString("abi/Goods.abi");

  public static final String BINARY = org.example.demo.utils.IOUtil.readResourceAsString("bin/ecc/Goods.bin");

  public static final String SM_BINARY = org.example.demo.utils.IOUtil.readResourceAsString("bin/sm/Goods.bin");

  @Value("${system.contract.goodsAddress}")
  private String address;
  
  @Value("${system.hexPrivateKey}")
  private String hexPrivateKeys;

  @Value("${system.account.names:}")
  private String accountNames;

  @Value("${system.account.addresses:}")
  private String accountAddresses;

  @Autowired
  private Client client;

  @Autowired
  private TransferTimeService transferTimeService;

  AssembleTransactionProcessor txProcessor;
  
  // 存储各个账户的密钥对
  private Map<String, CryptoKeyPair> accountKeyPairs = new HashMap<>();
  
  // 存储账户名与地址的映射
  private Map<String, String> nameToAddressMap = new HashMap<>();

  @PostConstruct
  public void init() throws Exception {
    this.txProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(this.client, this.client.getCryptoSuite().getCryptoKeyPair());
    
    // 初始化所有可用账户的密钥对
    if (hexPrivateKeys != null && !hexPrivateKeys.isEmpty()) {
      String[] privateKeys = hexPrivateKeys.split(",");
      for (String privateKey : privateKeys) {
        if (privateKey != null && !privateKey.trim().isEmpty()) {
          CryptoKeyPair keyPair = client.getCryptoSuite().createKeyPair(privateKey.trim());
          accountKeyPairs.put(keyPair.getAddress(), keyPair);
        }
      }
    }
    
    // 初始化账户名称和地址的映射
    if (accountNames != null && !accountNames.isEmpty() && accountAddresses != null && !accountAddresses.isEmpty()) {
      String[] names = accountNames.split(",");
      String[] addresses = accountAddresses.split(",");
      
      if (names.length == addresses.length) {
        for (int i = 0; i < names.length; i++) {
          nameToAddressMap.put(names[i].trim(), addresses[i].trim());
        }
      }
    }
  }

  public CallResponse owner() throws Exception {
    return this.txProcessor.sendCall(this.client.getCryptoSuite().getCryptoKeyPair().getAddress(), this.address, ABI, "owner", Arrays.asList());
  }

  public TransactionResponse addGoodsWithBO(GoodsAddGoodsInputBO input) throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "addGoods", input.toArgs());
  }

  public TransactionResponse updateGoodsWithBO(GoodsUpdateGoodsInputBO input) throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "updateGoods", input.toArgs());
  }

  public TransactionResponse resetGoodsIdWithResponse() throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "resetGoodsId", Arrays.asList());
  }

  public TransactionResponse removeGoodsWithBO(GoodsRemoveGoodsInputBO input) throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "removeGoods", input.toArgs());
  }

  public TransactionResponse transferGoodsWithBO(GoodsTransferGoodsInputBO input) throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "transferGoods", input.toArgs());
  }

  public CallResponse getGoodsWithBO(GoodsGetGoodsInputBO input) throws Exception {
    return this.txProcessor.sendCall(this.client.getCryptoSuite().getCryptoKeyPair().getAddress(), this.address, ABI, "getGoods", input.toArgs());
  }

  /**
   * 根据账户名或地址获取密钥对
   * 可以接受账户名称或账户地址
   */
  public CryptoKeyPair getKeyPairByAccount(String account) {
    if (account == null || account.isEmpty()) {
      return client.getCryptoSuite().getCryptoKeyPair();
    }
    
    // 检查是否是账户名称，如果是则转换为地址
    String address = account;
    if (nameToAddressMap.containsKey(account)) {
      address = nameToAddressMap.get(account);
    }
    
    // 根据地址查找密钥对
    if (accountKeyPairs.containsKey(address)) {
      return accountKeyPairs.get(address);
    }
    
    // 如果账户不存在，使用默认密钥对
    return client.getCryptoSuite().getCryptoKeyPair();
  }

  /**
   * 使用指定账户加载Goods合约
   */
  private Goods getGoodsContract(String account) {
    CryptoKeyPair keyPair = getKeyPairByAccount(account);
    return Goods.load(address, client, keyPair);
  }

  /**
   * 使用默认账户加载Goods合约
   */
  private Goods getGoodsContract() {
    return Goods.load(address, client, client.getCryptoSuite().getCryptoKeyPair());
  }

  /**
   * 添加商品（使用指定账户）
   */
  public TransactionReceipt addGoods(String name, String description, String account) {
    try {
      Goods goods = getGoodsContract(account);
      TransactionReceipt receipt = goods.addGoods(name, description);
      
      // 从交易事件中获取商品ID
      BigInteger goodsId = getGoodsIdFromAddEvent(receipt);
      
      // 记录初始所有者和时间
      transferTimeService.recordInitialOwner(goodsId.toString(), account);
      
      return receipt;
    } catch (Exception e) {
      throw new RuntimeException("添加商品失败: " + e.getMessage(), e);
    }
  }

  /**
   * 添加商品（使用默认账户）
   */
  public TransactionReceipt addGoods(String name, String description) {
    try {
      Goods goods = getGoodsContract();
      return goods.addGoods(name, description);
    } catch (Exception e) {
      throw new RuntimeException("添加商品失败: " + e.getMessage(), e);
    }
  }

  /**
   * 从添加商品事件中提取商品ID
   */
  public BigInteger getGoodsIdFromAddEvent(TransactionReceipt receipt) {
    List<Goods.GoodsCreatedEventResponse> events = getGoodsContract().getGoodsCreatedEvents(receipt);
    if (events != null && !events.isEmpty()) {
      return events.get(0).goodsId;
    }
    throw new RuntimeException("无法从事件中提取商品ID");
  }

  /**
   * 查询商品（使用指定账户）
   */
  public GoodsInfo getGoods(BigInteger goodsId, String account) {
    try {
      Goods goods = getGoodsContract(account);
      GoodsInfo goodsInfo = new GoodsInfo();
      
      // 使用异常处理机制区分新旧合约
      try {
        // 尝试新版合约调用 - 不直接使用Tuple7类型避免类型转换问题
        Method getGoodsMethod = goods.getClass().getMethod("getGoods", BigInteger.class);
        Object result = getGoodsMethod.invoke(goods, goodsId);
        
        // 通过反射获取Tuple的值
        Method getValue1 = result.getClass().getMethod("getValue1");
        Method getValue2 = result.getClass().getMethod("getValue2");
        Method getValue3 = result.getClass().getMethod("getValue3");
        Method getValue4 = result.getClass().getMethod("getValue4");
        Method getValue5 = result.getClass().getMethod("getValue5");
        Method getValue6 = result.getClass().getMethod("getValue6");
        
        goodsInfo.setId((BigInteger) getValue1.invoke(result));
        goodsInfo.setName((String) getValue2.invoke(result));
        goodsInfo.setDescription((String) getValue3.invoke(result));
        goodsInfo.setOwner((String) getValue4.invoke(result));
        
        // 获取历史所有者列表，确保值不为null
        Object historyOwners = getValue5.invoke(result);
        if (historyOwners != null) {
          goodsInfo.setHistoryOwners((List<String>) historyOwners);
          System.out.println("从智能合约获取的历史所有者: " + historyOwners);
        } else {
          goodsInfo.setHistoryOwners(new ArrayList<>());
          System.out.println("智能合约返回的历史所有者为null，已初始化为空列表");
        }
        
        goodsInfo.setCreateTime((BigInteger) getValue6.invoke(result));
        
        // 尝试获取第7个值(如果存在)
        try {
          Method getValue7 = result.getClass().getMethod("getValue7");
          Object ownershipTimestamps = getValue7.invoke(result);
          if (ownershipTimestamps != null) {
            goodsInfo.setOwnershipTimestamps((List<BigInteger>) ownershipTimestamps);
            System.out.println("从智能合约获取的所有权时间戳: " + ownershipTimestamps);
          } else {
            // 如果智能合约返回null，初始化为空列表
            goodsInfo.setOwnershipTimestamps(new ArrayList<>());
            System.out.println("智能合约返回的所有权时间戳为null，已初始化为空列表");
          }
        } catch (Exception e) {
          // 如果第7个值不存在，说明是旧合约，需要使用本地存储的时间戳
          System.out.println("未找到所有权时间戳，可能是旧版合约: " + e.getMessage());
          // 设置为空列表而不是null，避免前端处理问题
          goodsInfo.setOwnershipTimestamps(new ArrayList<>());
        }
      } catch (Exception e) {
        System.err.println("使用新合约格式获取数据失败，回退到旧格式: " + e.getMessage());
        
        // 旧版合约调用 - 使用原始的Tuple6
        Tuple6<BigInteger, String, String, String, List<String>, BigInteger> oldResult = goods.getGoods(goodsId);
        goodsInfo.setId(oldResult.getValue1());
        goodsInfo.setName(oldResult.getValue2());
        goodsInfo.setDescription(oldResult.getValue3());
        goodsInfo.setOwner(oldResult.getValue4());
        
        // 确保历史所有者列表不为null
        List<String> historyOwners = oldResult.getValue5();
        if (historyOwners != null) {
          goodsInfo.setHistoryOwners(historyOwners);
        } else {
          goodsInfo.setHistoryOwners(new ArrayList<>());
        }
        
        goodsInfo.setCreateTime(oldResult.getValue6());
        // 所有权时间戳初始化为空列表
        goodsInfo.setOwnershipTimestamps(new ArrayList<>());
      }
      
      // 从本地存储获取所有权转移时间戳
      List<Long> timestamps = transferTimeService.getTransferTimestamps(goodsId.toString());
      System.out.println("从本地存储获取的转移时间戳: " + (timestamps != null ? timestamps : "null") + 
                         ", 数量: " + (timestamps != null ? timestamps.size() : 0));
      
      // 如果从本地存储获取到了时间戳但合约中没有或长度不匹配，使用本地存储的时间戳
      if (timestamps != null && !timestamps.isEmpty()) {
        // 确保历史所有者列表存在
        if (goodsInfo.getHistoryOwners() == null) {
          goodsInfo.setHistoryOwners(new ArrayList<>());
        }
        
        // 将Long转换为BigInteger
        List<BigInteger> bigIntTimestamps = timestamps.stream()
            .map(BigInteger::valueOf)
            .collect(Collectors.toList());
        
        // 只有本地时间戳与历史所有者数量不匹配时，打印详细日志
        if (goodsInfo.getHistoryOwners().size() != bigIntTimestamps.size()) {
          System.out.println("警告: 历史所有者数量(" + goodsInfo.getHistoryOwners().size() + 
                            ")与时间戳数量(" + bigIntTimestamps.size() + ")不匹配");
          // 打印两者内容便于调试
          System.out.println("历史所有者: " + goodsInfo.getHistoryOwners());
          System.out.println("时间戳: " + bigIntTimestamps);
        }
        
        goodsInfo.setOwnershipTimestamps(bigIntTimestamps);
        System.out.println("设置本地存储的时间戳: " + bigIntTimestamps);
      }
      
      // 如果历史所有者和时间戳长度不一致，尝试使用本地存储的历史所有者
      if (goodsInfo.getHistoryOwners() != null && goodsInfo.getOwnershipTimestamps() != null && 
          goodsInfo.getHistoryOwners().size() != goodsInfo.getOwnershipTimestamps().size()) {
        List<String> localOwners = transferTimeService.getHistoryOwners(goodsId.toString());
        if (localOwners != null && !localOwners.isEmpty() && 
            localOwners.size() == goodsInfo.getOwnershipTimestamps().size()) {
          System.out.println("使用本地历史所有者替换不匹配的链上数据");
          goodsInfo.setHistoryOwners(localOwners);
        }
      }

      // 确保历史所有者和时间戳不为null（避免前端处理问题）
      if (goodsInfo.getHistoryOwners() == null) {
        goodsInfo.setHistoryOwners(new ArrayList<>());
      }
      
      if (goodsInfo.getOwnershipTimestamps() == null) {
        goodsInfo.setOwnershipTimestamps(new ArrayList<>());
      }
      
      // 打印最终处理后的数据情况
      System.out.println("最终处理后商品 " + goodsId + " 的历史所有者数量: " + 
                        goodsInfo.getHistoryOwners().size() + 
                        ", 时间戳数量: " + goodsInfo.getOwnershipTimestamps().size());
      
      return goodsInfo;
    } catch (ContractException e) {
      throw new RuntimeException("查询商品失败: " + e.getMessage(), e);
    }
  }

  /**
   * 查询商品（使用默认账户）
   */
  public GoodsInfo getGoods(BigInteger goodsId) {
    try {
      Goods goods = getGoodsContract();
      GoodsInfo goodsInfo = new GoodsInfo();
      
      // 使用异常处理机制区分新旧合约
      try {
        // 新版合约调用 - 不直接使用Tuple7类型避免类型转换问题
        Method getGoodsMethod = goods.getClass().getMethod("getGoods", BigInteger.class);
        Object result = getGoodsMethod.invoke(goods, goodsId);
        
        // 通过反射获取Tuple的值
        Method getValue1 = result.getClass().getMethod("getValue1");
        Method getValue2 = result.getClass().getMethod("getValue2");
        Method getValue3 = result.getClass().getMethod("getValue3");
        Method getValue4 = result.getClass().getMethod("getValue4");
        Method getValue5 = result.getClass().getMethod("getValue5");
        Method getValue6 = result.getClass().getMethod("getValue6");
        
        goodsInfo.setId((BigInteger) getValue1.invoke(result));
        goodsInfo.setName((String) getValue2.invoke(result));
        goodsInfo.setDescription((String) getValue3.invoke(result));
        goodsInfo.setOwner((String) getValue4.invoke(result));
        goodsInfo.setHistoryOwners((List<String>) getValue5.invoke(result));
        goodsInfo.setCreateTime((BigInteger) getValue6.invoke(result));
        
        // 尝试获取第7个值(如果存在)
        try {
          Method getValue7 = result.getClass().getMethod("getValue7");
          goodsInfo.setOwnershipTimestamps((List<BigInteger>) getValue7.invoke(result));
        } catch (Exception e) {
          // 如果第7个值不存在，说明是旧合约，忽略该异常
          System.out.println("未找到所有权时间戳，可能是旧版合约: " + e.getMessage());
        }
      } catch (Exception e) {
        System.err.println("使用新合约格式获取数据失败，回退到旧格式: " + e.getMessage());
        
        // 旧版合约调用 - 使用原始的Tuple6
        Tuple6<BigInteger, String, String, String, List<String>, BigInteger> oldResult = goods.getGoods(goodsId);
        goodsInfo.setId(oldResult.getValue1());
        goodsInfo.setName(oldResult.getValue2());
        goodsInfo.setDescription(oldResult.getValue3());
        goodsInfo.setOwner(oldResult.getValue4());
        goodsInfo.setHistoryOwners(oldResult.getValue5());
        goodsInfo.setCreateTime(oldResult.getValue6());
        // 所有权时间戳保持为null
      }
      
      return goodsInfo;
    } catch (ContractException e) {
      throw new RuntimeException("查询商品失败: " + e.getMessage(), e);
    }
  }

  /**
   * 更新商品（使用指定账户）
   */
  public TransactionReceipt updateGoods(BigInteger goodsId, String name, String description, String account) {
    try {
      Goods goods = getGoodsContract(account);
      return goods.updateGoods(goodsId, name, description);
    } catch (Exception e) {
      throw new RuntimeException("更新商品失败: " + e.getMessage(), e);
    }
  }

  /**
   * 更新商品（使用默认账户）
   */
  public TransactionReceipt updateGoods(BigInteger goodsId, String name, String description) {
    try {
      Goods goods = getGoodsContract();
      return goods.updateGoods(goodsId, name, description);
    } catch (Exception e) {
      throw new RuntimeException("更新商品失败: " + e.getMessage(), e);
    }
  }

  /**
   * 转移商品（使用指定账户）
   */
  public TransactionReceipt transferGoods(BigInteger goodsId, String toAddress, String account) {
    try {
      Goods goods = getGoodsContract(account);
      
      // 如果toAddress是账户名称，转换为地址
      String targetAddress = toAddress;
      if (nameToAddressMap.containsKey(toAddress)) {
        targetAddress = nameToAddressMap.get(toAddress);
      }
      
      System.out.println("转移商品 ID=" + goodsId + " 从账户 " + account + " 到账户 " + targetAddress);
      
      // 先查询商品当前所有者信息
      GoodsInfo goodsInfo = getGoods(goodsId, account);
      if (goodsInfo == null || !goodsInfo.getOwner().equalsIgnoreCase(account)) {
        throw new RuntimeException("转移失败：您不是商品 ID=" + goodsId + " 的所有者");
      }
      
      // 执行转移
      TransactionReceipt receipt = goods.transferGoods(goodsId, targetAddress);
      
      // 记录转移时间
      try {
        transferTimeService.recordTransfer(goodsId.toString(), targetAddress);
        System.out.println("成功记录商品 ID=" + goodsId + " 的转移时间和新所有者 " + targetAddress);
        
        // 立即保存记录到文件
        transferTimeService.triggerSave();
        System.out.println("已保存转移记录到文件");
      } catch (Exception e) {
        System.err.println("记录转移时间失败: " + e.getMessage());
        e.printStackTrace();
      }
      
      return receipt;
    } catch (Exception e) {
      throw new RuntimeException("转移商品失败: " + e.getMessage(), e);
    }
  }

  /**
   * 转移商品（使用默认账户）
   */
  public TransactionReceipt transferGoods(BigInteger goodsId, String toAddress) {
    try {
      Goods goods = getGoodsContract();
      
      // 如果toAddress是账户名称，转换为地址
      String targetAddress = toAddress;
      if (nameToAddressMap.containsKey(toAddress)) {
        targetAddress = nameToAddressMap.get(toAddress);
      }
      
      System.out.println("转移商品 ID=" + goodsId + " 到账户 " + targetAddress);
      
      // 执行转移
      TransactionReceipt receipt = goods.transferGoods(goodsId, targetAddress);
      
      // 记录转移时间
      try {
        transferTimeService.recordTransfer(goodsId.toString(), targetAddress);
        System.out.println("成功记录商品 ID=" + goodsId + " 的转移时间和新所有者 " + targetAddress);
        
        // 立即保存记录到文件
        transferTimeService.triggerSave();
        System.out.println("已保存转移记录到文件");
      } catch (Exception e) {
        System.err.println("记录转移时间失败: " + e.getMessage());
        e.printStackTrace();
      }
      
      return receipt;
    } catch (Exception e) {
      throw new RuntimeException("转移商品失败: " + e.getMessage(), e);
    }
  }

  /**
   * 删除商品（使用指定账户）
   */
  public TransactionReceipt removeGoods(BigInteger goodsId, String account) {
    try {
      Goods goods = getGoodsContract(account);
      TransactionReceipt receipt = goods.removeGoods(goodsId);
      
      // 删除本地记录
      transferTimeService.removeRecord(goodsId.toString());
      
      // 特殊处理：处理ID为1的商品被删除的情况
      // 当ID为1的商品被删除后，后续新商品可能会从ID=0开始分配
      // 确保ID=0的记录也被清理以避免所有者记录错误
      if (goodsId.intValue() == 1) {
        transferTimeService.removeRecord("0");
        System.out.println("商品ID=1被删除，同时清除ID=0的记录以防止所有者记录错误");
      }
      
      return receipt;
    } catch (Exception e) {
      throw new RuntimeException("删除商品失败: " + e.getMessage(), e);
    }
  }

  /**
   * 删除商品（使用默认账户）
   */
  public TransactionReceipt removeGoods(BigInteger goodsId) {
    try {
      Goods goods = getGoodsContract();
      TransactionReceipt receipt = goods.removeGoods(goodsId);
      
      // 删除本地记录
      transferTimeService.removeRecord(goodsId.toString());
      
      // 特殊处理：处理ID为1的商品被删除的情况
      // 当ID为1的商品被删除后，后续新商品可能会从ID=0开始分配
      // 确保ID=0的记录也被清理以避免所有者记录错误
      if (goodsId.intValue() == 1) {
        transferTimeService.removeRecord("0");
        System.out.println("商品ID=1被删除，同时清除ID=0的记录以防止所有者记录错误");
      }
      
      return receipt;
    } catch (Exception e) {
      throw new RuntimeException("删除商品失败: " + e.getMessage(), e);
    }
  }

  /**
   * 重置商品ID（使用指定账户）
   */
  public TransactionReceipt resetGoodsId(String account) {
    try {
      Goods goods = getGoodsContract(account);
      TransactionReceipt receipt = goods.resetGoodsId();
      
      // 重置后，清理所有本地转移记录，避免与新的商品ID混淆
      try {
        // 清理所有转移记录
        transferTimeService.clearAllRecords();
        System.out.println("商品ID重置，已清理所有本地转移记录以防止所有者记录错误");
      } catch (Exception e) {
        System.err.println("清理商品转移记录失败: " + e.getMessage());
        e.printStackTrace();
      }
      
      return receipt;
    } catch (Exception e) {
      throw new RuntimeException("重置商品ID失败: " + e.getMessage(), e);
    }
  }

  /**
   * 重置商品ID（使用默认账户）
   */
  public TransactionReceipt resetGoodsId() {
    try {
      Goods goods = getGoodsContract();
      TransactionReceipt receipt = goods.resetGoodsId();
      
      // 重置后，清理所有本地转移记录，避免与新的商品ID混淆
      try {
        // 清理所有转移记录
        transferTimeService.clearAllRecords();
        System.out.println("商品ID重置，已清理所有本地转移记录以防止所有者记录错误");
      } catch (Exception e) {
        System.err.println("清理商品转移记录失败: " + e.getMessage());
        e.printStackTrace();
      }
      
      return receipt;
    } catch (Exception e) {
      throw new RuntimeException("重置商品ID失败: " + e.getMessage(), e);
    }
  }

  /**
   * 从重置商品ID事件中提取新旧ID
   */
  public Map<String, BigInteger> getGoodsIdFromResetEvent(TransactionReceipt receipt) {
    List<Goods.GoodsIdResetEventResponse> events = getGoodsContract().getGoodsIdResetEvents(receipt);
    Map<String, BigInteger> result = new HashMap<>();
    
    if (events != null && !events.isEmpty()) {
      result.put("oldId", events.get(0).oldId);
      result.put("newId", events.get(0).newId);
      return result;
    }
    
    throw new RuntimeException("无法从事件中提取商品ID信息");
  }
  
  /**
   * 获取所有可用账户
   */
  public Map<String, String> getAllAccounts() {
    Map<String, String> allAccounts = new HashMap<>(nameToAddressMap);
    // 添加默认账户
    allAccounts.put("默认账户", client.getCryptoSuite().getCryptoKeyPair().getAddress());
    return allAccounts;
  }

  /**
   * 转移商品（使用指定账户和指定的当前所有者）
   * 此方法允许前端提供当前所有者信息，用于验证转移权限
   */
  public TransactionReceipt transferGoodsWithOwner(BigInteger goodsId, String toAddress, String account, String providedOwner) {
    try {
      Goods goods = getGoodsContract(account);
      
      // 如果toAddress是账户名称，转换为地址
      String targetAddress = toAddress;
      if (nameToAddressMap.containsKey(toAddress)) {
        targetAddress = nameToAddressMap.get(toAddress);
      }
      
      System.out.println("转移商品 ID=" + goodsId + " 从账户 " + account + " 到账户 " + targetAddress);
      System.out.println("前端提供的当前所有者: " + providedOwner);
      
      // 获取操作者的地址
      CryptoKeyPair keyPair = getKeyPairByAccount(account);
      String accountAddress = keyPair.getAddress();
      System.out.println("操作者地址: " + accountAddress);
      
      // 获取商品当前所有者信息，但不做权限验证
      GoodsInfo goodsInfo = getGoods(goodsId, account);
      if (goodsInfo == null) {
        throw new RuntimeException("转移失败：商品 ID=" + goodsId + " 不存在");
      }
      
      System.out.println("智能合约记录的所有者: " + goodsInfo.getOwner());
      
      // 验证前端提供的所有者信息与链上记录是否匹配
      if (!providedOwner.equalsIgnoreCase(goodsInfo.getOwner())) {
        System.out.println("警告：前端提供的所有者与链上记录不匹配，但尝试继续执行转移操作");
      }
      
      // 执行转移 - 跳过常规的所有者检查，由智能合约进行最终验证
      TransactionReceipt receipt = goods.transferGoods(goodsId, targetAddress);
      
      // 记录转移时间
      try {
        transferTimeService.recordTransfer(goodsId.toString(), targetAddress);
        System.out.println("成功记录商品 ID=" + goodsId + " 的转移时间和新所有者 " + targetAddress);
        
        // 立即保存记录到文件
        transferTimeService.triggerSave();
        System.out.println("已保存转移记录到文件");
      } catch (Exception e) {
        System.err.println("记录转移时间失败: " + e.getMessage());
        e.printStackTrace();
      }
      
      return receipt;
    } catch (Exception e) {
      throw new RuntimeException("转移商品失败: " + e.getMessage(), e);
    }
  }
}
